package com.hksj.data.event.listener;

import cn.hutool.core.util.IdUtil;
import com.hksj.data.event.WriteParseMysqlDataEvent;
import com.hksj.data.mysql.entity.DeviceMetadataParseInfo;
import com.hksj.data.mysql.service.DeviceMetadataParseInfoService;
import com.hksj.data.service.DevicePropertyService;
import com.hksj.data.thing.RawData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.data.util.Pair;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zengke
 * @version 1.0
 * @see WriteParseMysqlDataEventListener
 * @since 2025/08/15 10:23
 */

@Component
public class WriteParseMysqlDataEventListener {

    @Autowired
    private DevicePropertyService devicePropertyService;

    @Autowired
    private DeviceMetadataParseInfoService deviceMetadataParseInfoService;

    @Async
    @EventListener
    public void onWriteParseMysqlDataEvent(WriteParseMysqlDataEvent event) {

        //获取原始数据
        RawData data = event.getData();

        //获取时间戳
        Long timestamp = data.getTimestamp();

        //获取设备id
        String deviceId = data.getDeviceId();

        //判断设备id是否为空
        if (deviceId == null){
            return;
        }

        //获取数据集合
        Map<String, Object> dataMap = data.getDataMap();

        //判断数据集合是否为空
        if (dataMap == null){
            return;
        }

        //遍历数据集合、转换为设备属性解析列表
        List<DeviceMetadataParseInfo> deviceMetadataParseInfoList = dataMap.entrySet()
                .stream()
                .map(entry -> { //map的key为属性代码、value为属性值

                    //创建设备属性解析对象
                    DeviceMetadataParseInfo deviceMetadataParseInfo = new DeviceMetadataParseInfo();

                    //设置对象的各属性值
                    deviceMetadataParseInfo.setDeviceId(deviceId);
                    deviceMetadataParseInfo.setProperty(entry.getKey());
                    deviceMetadataParseInfo.setValue(String.valueOf(entry.getValue()));

                    //返回设备属性解析对象
                    return deviceMetadataParseInfo;
                }).collect(Collectors.toList());

        //封装设备属性解析对象列表的属性信息
        devicePropertyService.wrap(deviceMetadataParseInfoList);

        // 先查询已存在的记录
        Set<String> deviceIds = deviceMetadataParseInfoList.stream().map(DeviceMetadataParseInfo::getDeviceId).collect(Collectors.toSet());
        List<String> properties = deviceMetadataParseInfoList.stream().map(DeviceMetadataParseInfo::getProperty).collect(Collectors.toList());

        //已存在的记录集合
        Map<Pair<String, String>, DeviceMetadataParseInfo> existMap = deviceMetadataParseInfoService.lambdaQuery()
                .in(DeviceMetadataParseInfo::getDeviceId, deviceIds)
                .in(DeviceMetadataParseInfo::getProperty, properties)
                .list()
                .stream()
                .collect(Collectors.toMap(
                        item -> Pair.of(item.getDeviceId(), item.getProperty()),
                        Function.identity()
                ));

        // 设置ID，对于已存在的记录使用原有ID，新记录生成新ID
        deviceMetadataParseInfoList.forEach(item -> {
            Pair<String, String> key = Pair.of(item.getDeviceId(), item.getProperty());

            //获取设备属性解析对象
            DeviceMetadataParseInfo deviceMetadataParseInfo = existMap.get(key);

            //判断该对象是否为空
            if (ObjectUtils.isEmpty(deviceMetadataParseInfo)){

                //为空、设置创建时间、更新时间
                item.setCreateTime(new Date(timestamp));
                item.setUpdateTime(new Date(timestamp));

            } else {
                //不为空、设置id、更新时间
                item.setId(deviceMetadataParseInfo.getId());
                item.setUpdateTime(new Date(timestamp));
            }
        });

        //调用新增或更新的方法
        deviceMetadataParseInfoService.saveOrUpdateBatch(deviceMetadataParseInfoList);
    }
}
